package com.schedualnew.mq.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.schedualnew.mq.dto.esb.mq.send.SendESBEntry;
import com.schedualnew.mq.dto.exam.*;
import com.schedualnew.mq.dto.exam.autoschedule.ExamApplyItemBaseInfoDto;
import com.schedualnew.mq.dto.exam.schedule.QueryScheduledAppliesDto;
import com.schedualnew.mq.dto.exam.schedule.QueryScheduledApplyDto;
import com.schedualnew.mq.dto.exam.schedule.ScheduledExamApplyInfoDto;
import com.schedualnew.mq.entity.*;
import com.schedualnew.mq.mapper.*;
import com.schedualnew.mq.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;

@Service
public class ScheduleServiceImpl {

    private static final Logger logger = LogManager.getLogger(ScheduleServiceImpl.class);
    @Autowired
    private ExamScheduleMapper examScheduleMapper;

    @Autowired
    private ExamApplyMapper examApplyMapper;

    @Autowired
    private DictPrintPatternMapper dictPrintPatternMapper;

    @Autowired
    private ExamApplyPatientIdMapper patientIdMapper;

    @Autowired
    private DictSysparamsMapper dictSysparamsMapper;

    @Autowired
    private DictHospitalMapper dictHospitalMapper;

    @Autowired
    private DictDeptMapper deptMapper;

    @Autowired
    private ExamScheduleActMapper examScheduleActMapper;

    @Autowired
    private DictScheduleApmMapper dictScheduleApmMapper;

    @Autowired
    private ExamApplyItemMapper examApplyItemMapper;

    @Autowired
    private DictExamQueueMapper dictExamQueueMapper;

    @Autowired
    private DictCommonUseMapper dictCommonUseMapper;


    /**
     * 获取最近预约的打印信息
     *
     * @param dto
     * @return
     */
    public List<DictPrintPatternDto> getScheduledList(QueryScheduledApplyDto dto) {
        List<String> applyNoList = examScheduleMapper.querySickApplyNoList(dto);
        List<DictPrintPatternDto> result = new ArrayList<>();
        for (String item : applyNoList) {
            ExamApplyDto dto1 = new ExamApplyDto();
            dto1.setApplyNo(item);
            dto1.setTerminalType(ConstantsUtil.TerminalType.SELF.getType());
            DictPrintPatternDto print = null;
            try {
                print = print(dto1);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            result.add(print);
        }
        return result;
    }


    /**
     * 获取最近预约的打印信息
     *
     * @param dto
     * @return
     */
    public List<DictPrintPatternDto> getScheduledListByDate(QueryScheduledApplyDto dto) {
        List<String> applyNoList = examScheduleMapper.querySickApplyNoListByScheduleDate(dto);
        List<DictPrintPatternDto> result = new ArrayList<>();
        for (String item : applyNoList) {
            ExamApplyDto dto1 = new ExamApplyDto();
            dto1.setApplyNo(item);
            dto1.setTerminalType(ConstantsUtil.TerminalType.SELF.getType());
            DictPrintPatternDto print = null;
            try {
                print = print(dto1);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            result.add(print);
        }
        return result;
    }

    /**
     * @param dto
     * @return
     * @description
     * @author ryan.li
     * @date 2022/10/7 8:53
     */

    public DictPrintPatternDto print(ExamApplyDto dto) throws Exception {
        if (StringUtils.isBlank(dto.getApplyNo())) {
            throw new Exception("申请单号不能为空");
        }
        if (StringUtils.isBlank(dto.getTerminalType())) {
            throw new Exception("终端类型不能为空");
        }
        List<ExamApplyDto> applies = new ArrayList<>();
        Set<String> set = new HashSet<>();
        Map<String, String> megerNoMap = new HashMap<>();
        ExamApplyDto eaDto = new ExamApplyDto();
        List<String> reqMemos = new ArrayList<>();
        Set<String> flags = new HashSet<>();
        if (StringUtils.isNotBlank(dto.getMergeNo())) {
            String[] split = dto.getMergeNo().split(",");
            for (String s : split) {
                eaDto.setApplyNo(s.substring(0, s.lastIndexOf("-")));
                eaDto.setItemNo(Integer.valueOf(s.substring(s.lastIndexOf("-") + 1)));
                List<ExamApplyDto> examApplyDtos = examApplyMapper.findByApplyNo(eaDto);
                if (examApplyDtos.isEmpty()) {
                    throw new Exception("打印失败请重试");
                }
                ExamApplyDto examApplyDto = examApplyDtos.get(0);
                if (set.add(examApplyDto.getExamNo())) {
                    applies.add(examApplyDto);
                    megerNoMap.put(examApplyDto.getExamNo(), s);
                } else {
                    String megerNo = megerNoMap.get(examApplyDto.getExamNo());
                    megerNoMap.put(examApplyDto.getExamNo(), megerNo + "," + s);
                }
                if (!reqMemos.contains(examApplyDto.getReqMemo())) {
                    reqMemos.add(examApplyDto.getReqMemo());
                }
                if (StringUtils.isNotBlank(examApplyDto.getFlags())) {
                    flags.add(examApplyDto.getFlags());
                }
            }
        } else {
            eaDto.setApplyNo(dto.getApplyNo());
            ExamApplyDto examApplyDto2 = examApplyMapper.findByApplyNo(eaDto).get(0);
            if (examApplyDto2 != null && set.add(examApplyDto2.getExamNo())) {
                applies.add(examApplyDto2);
            }
        }
        if (CollectionUtils.isEmpty(applies)) {
            String strReturn = "您的检查申请单信息不存在，如有疑问请到护士站咨询";
            throw new Exception(strReturn);
        }

        ExamApplyDto ea = applies.get(0);
        ea.setReqMemo(StringUtils.join(reqMemos, ","));
        ea.setFlags(StringUtils.join(flags, ","));
        logger.info("{}检查状态:{} ,{}预约状态:{},模板类型:{},examStatus:{},scheduleStatus:{}", ea.getApplyNo(),
                ea.getExamStatus(), ea.getApplyNo(), ea.getScheduleStatus(), dto.getPatternType(),
                ea.getExamStatus(), ea.getScheduleStatus());
        String actType = "";
        if (StringUtils.isBlank(dto.getPatternType())) {
            if (ConstantsUtil.ScheduleStatus.EIGHT.getStatus().equals(ea.getScheduleStatus())) {
                dto.setPatternType("0");
                actType = ConstantsUtil.ActType.SCHE_PRINT.getType();
            } else {
                if (!"10,20,40,50,70".contains(ea.getExamStatus())) {
                    logger.info("@{}@,预约状态:{}", ea.getApplyNo(), (StringUtils.isNotBlank(ea.getExamStatus()) ? ea.getExamStatus() : ea.getScheduleStatus()));
                    throw new Exception("没有预约申请或已检查！");
                }
                dto.setPatternType("1");
                actType = ConstantsUtil.ActType.SIGN_PRINT.getType();
            }
        }
        String examClass = ea.getExamClass();
        String patientsource = ea.getPatientSource();
        String queueName = ea.getQueueName();
        String terminalType = dto.getTerminalType();


        /**
         * 查询构建打印设置
         */
        DictPrintPatternDto printPatternDto = new DictPrintPatternDto();
        printPatternDto.setPatternType(dto.getPatternType());
        printPatternDto.setExamClass(examClass);
        printPatternDto.setTerminalType(terminalType);
        List<DictPrintPatternDto> printConfigs = dictPrintPatternMapper.getPatternList(printPatternDto);
        for (DictPrintPatternDto patternDto : printConfigs) {
            patternDto.setTerminalTypes(CommonUtil.split2List(patternDto.getTerminalType()));
            patternDto.setQueueNames(CommonUtil.split2List(patternDto.getQueueName()));
        }
        if (printConfigs.isEmpty()) {
            throw new Exception("未查询到凭条模板,请添加模板后重试!");
        }
        printConfigs.removeIf(schedulePrint -> StringUtils.isNotBlank(schedulePrint.getQueueName()) && !schedulePrint.getQueueName().contains(queueName));


        int level = 0;
        String patternContent = "";
        String width = "";
        String height = "";
        for (DictPrintPatternDto printConfig : printConfigs) {
            boolean isExamClass = ((printConfig.getExamClass() != null) ? printConfig.getExamClass() : "").equals(examClass);
            boolean isPatientSource = ((printConfig.getPatientSource() != null) ? printConfig.getPatientSource() : "").contains(patientsource);
            boolean isQueueName = ((printConfig.getQueueName() != null) ? ("," + printConfig.getQueueName() + ",") : "").contains("," + queueName + ",");
            boolean isTerminalType = ((printConfig.getTerminalType() != null) ? ("," + printConfig.getTerminalType() + ",") : "").contains("," + terminalType + ",");
            if (level < 1 && isExamClass && isTerminalType && !isQueueName && !isPatientSource) {
                patternContent = printConfig.getPatternContent();
                width = printConfig.getWidth();
                height = printConfig.getHeight();
                level = 1;
            }
            if (level < 2 && isExamClass && !isQueueName && isTerminalType && isPatientSource) {
                patternContent = printConfig.getPatternContent();
                width = printConfig.getWidth();
                height = printConfig.getHeight();
                level = 2;
            } else if (level < 3 && isExamClass && !isPatientSource && isTerminalType && isQueueName) {
                patternContent = printConfig.getPatternContent();
                width = printConfig.getWidth();
                height = printConfig.getHeight();
                level = 3;
            } else {
                if (isExamClass && isQueueName && isPatientSource && isTerminalType) {
                    patternContent = printConfig.getPatternContent();
                    width = printConfig.getWidth();
                    height = printConfig.getHeight();
                    break;
                }
            }
        }
        String content = "";
        String no = ea.getSickId();
        if ("1".equals(dto.getPatternType())) {
            no = ea.getExamNo();
        }
        ExamApplyPatientId examApplyPatientId = new ExamApplyPatientId();
        examApplyPatientId.setSickId(ea.getSickId());
        examApplyPatientId.setDomainId("0007");
        List<ExamApplyPatientId> ids = selectd(examApplyPatientId);
        String icCard = ea.getIcCard();
        if (!ids.isEmpty()) {
            icCard = (StringUtils.isNotBlank(ids.get(0).getPatientId()) ? ids.get(0).getPatientId() : ea.getIcCard());
        }
        String PrintByExamNo = getConfigByName(ConstantsUtil.ConfigName.PRINT_BY_EXAM_NO.getKey());
        boolean isExamNos = ((PrintByExamNo != null) ? PrintByExamNo : "").contains(ea.getExamClass());
        dto.setActType(actType);
        List<Map<String, Object>> mapList = new ArrayList<>();
        if (isExamNos && applies.size() > 1) {
            for (ExamApplyDto applyDto : applies) {
                HashMap<String, Object> map = new HashMap<String, Object>();
                dto.setApplyNo(applyDto.getApplyNo());
                dto.setMergeNo(megerNoMap.get(applyDto.getExamNo()));
                map.put("CODE_CARD", icCard);
                converPatternMap(applyDto, map, dto, null);
                String barCode = "data:image/png;base64," + EncoderUtil.barcode(applyDto.getExamNo(), 210, 50);
                map.put("BAR_CODE", barCode);
                String qrCode = "data:image/png;base64," + QrCodeUtil.creatRrCode(ea.getApplyNo(), 150, 150);
                map.put("QR_CODE", qrCode);
                String cloudFilmUrl_tmp = getConfigByName(ConstantsUtil.ConfigName.CLOUD_FILM_URL.getKey());
                if (StringUtils.isNotBlank(cloudFilmUrl_tmp)) {
                    String cloudFilmUrl = CommonUtil.replaceMsg(cloudFilmUrl_tmp, map);
                    String cloudFilmUrlCode = "data:image/png;base64," + QrCodeUtil.creatRrCode(cloudFilmUrl, 150, 150);
                    map.put("CLOUD_FILM_URL", cloudFilmUrlCode);
                }
                if (StringUtils.isNotBlank(ea.getIcCard())) {
                    String qrCode_icCard = "data:image/png;base64," + QrCodeUtil.creatRrCode(icCard, 150, 150);
                    map.put("QR_CODE_ICCARD", qrCode_icCard);
                }
                if (StringUtils.isNotBlank(ea.getInpatientNo())) {
                    String qrCode_inpatientNo = "data:image/png;base64," + QrCodeUtil.creatRrCode((ea.getInpatientNo() != null) ? ea.getInpatientNo() : "", 150, 150);
                    map.put("QR_CODE_INPATIENTNO", qrCode_inpatientNo);
                }
                if (StringUtils.isNotBlank(ea.getOutpatientNo())) {
                    String qrCode_outpatientNo = "data:image/png;base64," + QrCodeUtil.creatRrCode((ea.getOutpatientNo() != null) ? ea.getOutpatientNo() : "", 150, 150);
                    map.put("QR_CODE_OUTPATIENTNO", qrCode_outpatientNo);
                }
                if (getPatientSourceIn().equals(ea.getPatientSource())) {
                    String qrCode_inpatNo = "data:image/png;base64," + QrCodeUtil.creatRrCode((ea.getInpatientNo() != null) ? ea.getInpatientNo() : "", 150, 150);
                    map.put("QR_CODE_INPATNO_CARD", qrCode_inpatNo);
                } else {
                    String qrCode_icCard = "data:image/png;base64," + QrCodeUtil.creatRrCode((icCard != null) ? icCard : "", 150, 150);
                    map.put("QR_CODE_INPATNO_CARD", qrCode_icCard);
                }
                int printCnt = (applyDto.getPrintCnt() != null) ? Integer.parseInt(applyDto.getPrintCnt()) : 0;
                map.put("PRINTCNT", printCnt + 1);
                mapList.add(map);
            }
        } else {
            HashMap<String, Object> map = new HashMap<>();
            map.put("CODE_CARD", icCard);
            converPatternMap(ea, map, dto, null);
            String barCode2 = "data:image/png;base64," + EncoderUtil.barcode(no, 210, 50);
            map.put("BAR_CODE", barCode2);
            String qrCode2 = "data:image/png;base64," + QrCodeUtil.creatRrCode(ea.getApplyNo(), 100, 100);
            map.put("QR_CODE", qrCode2);
            String cloudFilmUrl_tmp2 = getConfigByName(ConstantsUtil.ConfigName.CLOUD_FILM_URL.getKey());
            if (StringUtils.isNotBlank(cloudFilmUrl_tmp2)) {
                String cloudFilmUrl2 = CommonUtil.replaceMsg(cloudFilmUrl_tmp2, map);
                String cloudFilmUrlCode2 = "data:image/png;base64," + QrCodeUtil.creatRrCode(cloudFilmUrl2, 150, 150);
                map.put("CLOUD_FILM_URL", cloudFilmUrlCode2);
            }
            if (StringUtils.isNotBlank(ea.getIcCard())) {
                String qrCode_icCard2 = "data:image/png;base64," + QrCodeUtil.creatRrCode(icCard, 150, 150);
                map.put("QR_CODE_ICCARD", qrCode_icCard2);
            }
            if (StringUtils.isNotBlank(ea.getInpatientNo())) {
                String qrCode_inpatientNo2 = "data:image/png;base64," + QrCodeUtil.creatRrCode((ea.getInpatientNo() != null) ? ea.getInpatientNo() : "", 150, 150);
                map.put("QR_CODE_INPATIENTNO", qrCode_inpatientNo2);
            }
            if (StringUtils.isNotBlank(ea.getOutpatientNo())) {
                String qrCode_outpatientNo2 = "data:image/png;base64," + QrCodeUtil.creatRrCode((ea.getOutpatientNo() != null) ? ea.getOutpatientNo() : "", 150, 150);
                map.put("QR_CODE_OUTPATIENTNO", qrCode_outpatientNo2);
            }
            if (getPatientSourceIn().equals(ea.getPatientSource())) {
                String qrCode_inpatNo2 = "data:image/png;base64," + QrCodeUtil.creatRrCode((ea.getInpatientNo() != null) ? ea.getInpatientNo() : "", 150, 150);
                map.put("QR_CODE_INPATNO_CARD", qrCode_inpatNo2);
            } else {
                String qrCode_icCard2 = "data:image/png;base64," + QrCodeUtil.creatRrCode((icCard != null) ? icCard : "", 150, 150);
                map.put("QR_CODE_INPATNO_CARD", qrCode_icCard2);
            }
            int printCnt = (ea.getPrintCnt() != null) ? Integer.parseInt(ea.getPrintCnt()) : 0;
            map.put("PRINTCNT", printCnt + 1);
            mapList.add(map);
        }
        content = JsonUtil.toJson(mapList);
        logger.info("模板内容:{}", content);

        //content += CommonUtil.replaceMsg(patternContent, mapList);
        DictPrintPatternDto dictPrintPatternDto = new DictPrintPatternDto();
        dictPrintPatternDto.setPatternContent(content);
        dictPrintPatternDto.setBarCode(no);
        dictPrintPatternDto.setPatternHeight((height != null) ? height : "");
        dictPrintPatternDto.setPatternWidth((width != null) ? width : "");

        int printCnt = (ea.getPrintCnt() != null) ? Integer.parseInt(ea.getPrintCnt()) : 0;
        ExamSchedule es = new ExamSchedule();
        es.setScheduledId(ea.getScheduledId());
        es.setPrintCnt(printCnt + 1);

        // 修改保存预约ID
        editExamScheduleById(es);

        return dictPrintPatternDto;
    }


    /**
     * 根据患者id查询患者信息
     *
     * @param dto
     * @return
     */
    public List<ExamApplyPatientId> selectd(ExamApplyPatientId dto) {
        Map<String, Object> map = new HashMap<>();
        map.put("SICK_ID", dto.getSickId());
        map.put("DOMAIN_ID", dto.getDomainId());
        map.put("PATIENT_ID", dto.getPatientId());
        map.put("HOSPITAL_CODE", dto.getHospitalCode());
        QueryWrapper<ExamApplyPatientId> qw = new QueryWrapper<>();
        qw.allEq(map, false);
        return patientIdMapper.selectList(qw);
    }


    @Cacheable(value = {"configCache"}, key = "#paramName")
    public String getConfigByName(String paramName) {
        if (StringUtils.isBlank(paramName)) {
            return null;
        }
        logger.info("----------------缓存configCache[paramName:{}]-------------------", paramName);
        String paramValue = "";
        DictSysparamsDto dsDto = new DictSysparamsDto();
        dsDto.setParamName(paramName);
        List<DictSysparamsDto> dictSysparamsList = dictSysparamsMapper.selectSysparmsInfoList(dsDto);
        if (dictSysparamsList != null && dictSysparamsList.size() > 0) {
            paramValue = dictSysparamsList.get(0).getParamValue();
            if (StringUtils.isBlank(paramValue)) {
                paramValue = dictSysparamsList.get(0).getDataValue();
            }
        }
        return paramValue;
    }

    public String getPatientSourceIn() {
        String patientSourceIn = getConfigByName(ConstantsUtil.ConfigName.PATIENT_SOURCE_IN.getKey());
        if (StringUtils.isNotBlank(patientSourceIn)) {
            return patientSourceIn;
        }
        return "住院";
    }


    /**
     * 构建打印参数
     *
     * @param ea
     * @param map
     * @param dto
     * @param smsType
     */
    public void converPatternMap(ExamApplyDto ea, HashMap<String, Object> map, ExamApplyDto dto, String smsType) {
        if (StringUtils.isNotBlank(ea.getExamNo())) {
            map.put("NO_", CommonUtil.toDecimal(Long.parseLong("1" + ea.getExamNo())));
        }

        map.put("IMG_NO", ea.getImgNo());
        map.put("PACS_SORT_NO", ea.getPacsSortNo());
        map.put("PACS_EXAM_DEPT", ea.getPacsExamDept());
        map.put("PLAT_EXAM_TIME", ea.getPlanExamTime());

        map.put("CASE_NO", ea.getCaseNo());
        map.put("HEIGHT", ea.getHeight());
        map.put("WEIGHT", ea.getWeight());
        map.put("EXAM_NO", ea.getExamNo());
        map.put("NURSE_UNIT", ea.getNurseUnit());
        map.put("IC_CARD", ea.getIcCard());
        map.put("SICK_ID", ea.getSickId());
        map.put("INPATIENT_NO", ea.getInpatientNo());
        map.put("PAT_LOCAL_ID", ea.getPatLocalId());
        map.put("QUEUE_NO", ea.getQueueNo());
        map.put("SCHEDULE_NO", ea.getScheduleNo());
        map.put("APPLY_NO", ea.getApplyNo());
        map.put("NAME", ea.getName());
        map.put("SEX", ea.getSex());
        map.put("AGE", ea.getAge());
        map.put("BED_NO", ea.getBedNo());
        map.put("PERFORM_DEPT_NAME", ea.getPerformDeptName());
        map.put("REQ_WARD_NAME", ea.getReqWardName());
        map.put("EXAM_CLASS", ea.getExamClass());
        map.put("SCHEDULE_DATE", ea.getScheduleDate());
        map.put("EXAM_SUB_CLASS", ea.getExamSubClass());
        map.put("DRUGTIME", ea.getDrugTime());
        map.put("PATIENT_SOURCE", ea.getPatientSource());
        map.put("MEMO", ea.getReqMemo());
        map.put("TRANS_TOOL", ea.getTransTool());
        map.put("PRINT_SYSTEM_TIME", DateUtils.getDateTime());
        map.put("REQ_PHYSICIAN", ea.getReqPhysician());
        map.put("PHYS_SIGN", ea.getPhysSign());
        map.put("CLIN_SYMP", ea.getClinSymp());
        map.put("CLIN_DIAG", ea.getClinDiag());
        map.put("RELEVANT_DIAG", ea.getRelevantDiag());
        map.put("RELEVANT_LAB_TEST", ea.getRelevantLabTest());
        map.put("REQ_DATE", ea.getReqDate());
        map.put("REQ_TIME", ea.getReqTime());
        map.put("PRIORITY_ORDER", ea.getPriorityOrder());
        map.put("OUTPATIENT_NO", ea.getOutpatientNo());
        map.put("OUT_REG_NO", ea.getOutRegNo());
        map.put("MAILING_ADDRESS", ea.getMailingAddress());
        map.put("PHONE_NUMBER", ea.getPhoneNumber());
        map.put("BIRTH_DATE", ea.getBirthDate());
        map.put("QUEUE_NAME", ea.getQueueName());
        map.put("EXAM_QUEUE", ea.getExamQueueName());
        map.put("SCHEDULE_MEMO", ea.getMemo());
        map.put("APM_NAME", ea.getScheduleApm());
        map.put("CHARGE", ea.getCharges());
        map.put("QUEUE_ALIAS", ea.getQueueAlias());
        map.put("WARD_PHONE", ea.getWardPhoneNumber());
        map.put("RESERVE1", ea.getReserve1());
        map.put("SCHE_LOCATION", ea.getLocation());
        map.put("EXAM_LOCATION", ea.getExamLocation());
        map.put("CHARGE_TYPE", ea.getChargeType());
        map.put("LIST_APPLY_NO", StringUtils.join(CommonUtil.mergeNo2ApplyNos(dto.getMergeNo()), ","));
        if (StringUtils.isNotBlank(ea.getExamStatus()) && StringUtils.isNotBlank(ea.getExamLocation())) {
            map.put("LOCATION", ea.getExamLocation());
        } else {
            map.put("LOCATION", ea.getLocation());
        }
        if (StringUtils.isBlank(ea.getReqDeptName())) {
            QueryWrapper<DictDept> qw = new QueryWrapper<>();
            qw.eq("DEPT_CODE", ea.getDeptCode());
            List<DictDept> dictDepts = deptMapper.selectList(qw);

            if (!CollectionUtils.isEmpty(dictDepts)) {
                map.put("REQ_DEPT_NAME", StringUtils.isBlank(dictDepts.get(0).getDeptName()) ? "" : dictDepts.get(0).getDeptName());
            }
        } else {
            map.put("REQ_DEPT_NAME", ea.getReqDeptName());
        }
        // 打印次数限制
        ExamScheduleActDto actDto = new ExamScheduleActDto();
        actDto.setScheduledId(ea.getScheduledId());
        actDto.setTerminalType(dto.getTerminalType());
        actDto.setActType(dto.getActType());
        if (StringUtils.isBlank(ea.getExamStatus())) {
            actDto.setActType(ConstantsUtil.ActType.SCHE_PRINT.getType());
            if (Objects.equals("3", ea.getScheduleStatus())) {
                actDto.setActType(ConstantsUtil.ActType.SIGN_PRINT.getType());
            }
        } else if ("10,20,40,50".contains(ea.getExamStatus())) {
            actDto.setActType(ConstantsUtil.ActType.SIGN_PRINT.getType());
        }

        QueryWrapper<ExamScheduleAct> qw = new QueryWrapper<>();
        qw.eq("SCHEDULED_ID", actDto.getScheduledId());
        qw.eq("TERMINAL_TYPE", actDto.getTerminalType());
        qw.eq("ACT_TYPE", actDto.getActType());
        logger.info("getScheduledId:{},getTerminalType:{},getActType:{}", actDto.getScheduledId(), actDto.getTerminalType(), actDto.getActType());
        Long resultCount = examScheduleActMapper.selectCount(qw);
        int printCnt = (resultCount != null) ? resultCount.intValue() : 0;

        if (printCnt > 1) {
            map.put("PRINTCNT", printCnt + "(补打)");
        } else {
            map.put("PRINTCNT", printCnt);
        }
        map.put("ARRIVE_TIME", ea.getScheduleApm().replace("~", "-").split("-")[0]);
        if (StringUtils.isNotBlank(ea.getScheduleHospital())) {
            QueryWrapper<DictHospital> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("HOSPITAL_CODE", ea.getScheduleHospital());
            DictHospital hospital = dictHospitalMapper.selectOne(queryWrapper);
            map.put("PERFORM_HOSPITAL_NAME", hospital.getHospitalName());
        }
        DictScheduleApmDto apmMap = new DictScheduleApmDto();
        String startTime = "";
        String endTime = "";
        if (StringUtils.isNotBlank(ea.getApmCode())) {
            apmMap = getTimeEarliest(ea.getApmCode());
            map.put("TIME_SIGNIN", apmMap.getTimeSignin());
            map.put("TIME_EARLIEST", apmMap.getTimeEarliest());
            startTime = apmMap.getTimeStart().substring(0, apmMap.getTimeStart().length() - 3);
            endTime = DateUtils.addSecond(apmMap.getTimeEnd(), 1);
            endTime = endTime.substring(0, apmMap.getTimeEnd().length() - 3);
            map.put("SCHEDULE_APM", startTime + "~" + endTime);
            map.put("APM_NAME", apmMap.getScheduleApm());
        }
        List<ExamApplyItemDto> items = getExamApplyItem(dto.getMergeNo(), dto);
        ea.setItems(items);
        if (!CollectionUtils.isEmpty(items)) {
            List<String> itemNames = new ArrayList<>();
            List<String> notices = new ArrayList<>();
            List<String> requestList = new ArrayList<>();
            List<String> orderNos = new ArrayList<>();
            List<String> item_order = new ArrayList<>();
            for (int i = 0; i < items.size(); ++i) {
                if (orderNos.contains(items.get(i).getOrderNo())) {
                    orderNos.add(items.get(i).getOrderNo());
                }
                int amount = (items.get(i).getAmount() != null) ? new BigDecimal(items.get(i).getAmount()).intValue() : 1;
                if (amount > 1) {
                    itemNames.add("；" + items.get(i).getItemName() + " 00d7" + amount);
                } else {
                    itemNames.add(i + 1 + ":" + items.get(i).getItemName());
                    item_order.add(i + 1 + ":" + items.get(i).getItemName() + " <" + items.get(i).getOrderNo() + ">");
                }
                if (StringUtils.isNotBlank(items.get(i).getNotice())) {
                    notices.add(items.get(i).getNotice());
                }
                requestList.add((items.get(i).getExamRequire() != null) ? items.get(i).getExamRequire() : "");
            }
            map.put("ORDER_NO", String.join(";", orderNos));
            if (!CollectionUtils.isEmpty(requestList)) {
                List<String> examRequest = new ArrayList<String>(new TreeSet<String>(requestList));
                map.put("EXAM_REQUIRE", StringUtils.join(examRequest, ","));
            } else {
                map.put("EXAM_REQUIRE", "");
            }
            List<String> newNotices = (List<String>) CommonUtil.convertNotice(notices, ea.getPatientSource(), endTime, ea.getBirthDate());
            if (newNotices != null && newNotices.size() > 0) {
                map.put("BR_NOTICE", StringUtils.join(newNotices, "</br>"));
                map.put("NOTICE", StringUtils.join(newNotices, ""));
            } else {
                map.put("BR_NOTICE", "");
                map.put("NOTICE", "");
            }
            if (!itemNames.isEmpty()) {
                map.put("BR_ITEM_NAME", StringUtils.join(itemNames, "</br>"));
                map.put("BR_ITEM_ORDER", StringUtils.join(item_order, "</br>"));
                map.put("ITEM_NAME", StringUtils.join(itemNames, "；"));
            } else {
                map.put("BR_ITEM_NAME", "");
                map.put("ITEM_NAME", "");
            }
        }
        String type = ConstantsUtil.ReminderType.SCHEDULE.getType();
        if ("10".equals(ea.getExamStatus())) {
            type = ConstantsUtil.ReminderType.SIGN.getType();
        }
        List<String> reminders = new ArrayList<>();

        QueryWrapper<DictExamQueue> query = new QueryWrapper<>();
        query.eq("QUEUE_NAME", ea.getQueueName());
        query.orderByAsc("SORT_NO");
        List<DictExamQueue> queues = dictExamQueueMapper.selectList(query);

        if (!queues.isEmpty() && StringUtils.isNotBlank(queues.get(0).getNotice())) {
            reminders.add(queues.get(0).getNotice());
        }
        if (reminders.size() < 1) {
            reminders.addAll(getReminders(type, ea.getExamClass(), dto.getTerminalType()));
        }
        List<String> newRemi = CommonUtil.convertNotice(reminders, ea.getPatientSource(), endTime, ea.getBirthDate());
        if (!CollectionUtils.isEmpty(newRemi)) {
            map.put("REMINDER", StringUtils.join(newRemi, ","));
            map.put("BR_REMINDER", StringUtils.join(newRemi, "</br>"));
        } else {
            map.put("REMINDER", "");
            map.put("BR_REMINDER", "");
        }
        double maxLimit = (apmMap.getMaxLimit() == null) ? 0.0 : apmMap.getMaxLimit();
        int apmLength = (apmMap.getApmLength() == null) ? 0 : apmMap.getApmLength();
        double avg = apmLength / maxLimit;
        double sTime = 0.0;
        double eTime = 0.0;
        double nextTime = 0.0;
        ExamScheduleDto scheduleDto = new ExamScheduleDto();
        scheduleDto.setApmCode(ea.getApmCode());
        scheduleDto.setScheduleApmCodes(CommonUtil.split2List(ea.getApmCode()));
        scheduleDto.setScheduleApms(CommonUtil.split2List(ea.getScheduleApm()));
        scheduleDto.setScheduledDate(ea.getScheduleDate());
        scheduleDto.setQueueNames(CommonUtil.split2List(ea.getQueueName()));
        scheduleDto.setIsExamClassRatio(getOrganExamClassList().contains(dto.getExamClass()));
        scheduleDto.setScheduleStatus("1");
        List<ExamSchedule> ess = getExamScheduleByNxtApm(scheduleDto);
        if (ess != null && !ess.isEmpty()) {
            for (ExamSchedule examSchedule : ess) {
                String nextApmRatio = examSchedule.getNextApmRatio().substring(examSchedule.getNextApmRatio().lastIndexOf("\\|") + 1);
                double nextOrgans = Double.parseDouble(nextApmRatio.substring(nextApmRatio.lastIndexOf("=") + 1));
                DictScheduleApmDto nextApm = getTimeEarliest(examSchedule.getApmCode());
                double nextAvg = nextApm.getApmLength() / nextApm.getMaxLimit();
                nextTime += nextOrgans * nextAvg;
            }
        }
        List<ScheduleDetailDto> scheduleList = examScheduleMapper.getScheduleList(scheduleDto);
        if (!scheduleList.isEmpty()) {
            Collections.sort(scheduleList, (o1, o2) -> {
                if (StringUtils.isNotBlank(o1.getExamQueueNo()) && StringUtils.isNotBlank(o2.getExamQueueNo())) {
                    return (o1.getExamQueueNo().hashCode() > o2.getExamQueueNo().hashCode()) ? 0 : -1;
                }
                if (StringUtils.isNotBlank(o1.getQueueNo()) && StringUtils.isNotBlank(o2.getQueueNo())) {
                    return (o1.getQueueNo().hashCode() > o2.getQueueNo().hashCode()) ? 0 : -1;
                }
                return 0;
            });
            for (ScheduleDetailDto scheduleDetailDto : scheduleList) {
                double organs = (scheduleDetailDto.getOrgans() != null) ? scheduleDetailDto.getOrgans() : 1.0;
                sTime = eTime;
                eTime += avg * organs;
                if (ea.getApplyNo().equals(scheduleDetailDto.getApplyNo())) {
                    break;
                }
            }
            String[] startTimeArr = startTime.split(":");
            int h = Integer.parseInt(startTimeArr[0]);
            int m = (int) nextTime + Integer.parseInt(startTimeArr[1]);
            sTime += m;
            eTime += m;
            int sh = (int) sTime / 60 + h;
            int sm = (int) sTime % 60;
            int eh = (int) eTime / 60 + h;
            int em = (int) eTime % 60;
            map.put("EXAM_END_APM", String.format("%02d", eh) + ":" + String.format("%02d", em));
            map.put("EXAM_START_APM", String.format("%02d", sh) + ":" + String.format("%02d", sm));
        }
        if (StringUtils.isNotBlank(ea.getLastMensesDate()) || StringUtils.isNotBlank(ea.getPregnancyDate())) {
            int pregnantDays = 0;
            if (StringUtils.isNotBlank(ea.getLastMensesDate())) {
                pregnantDays = DateUtils.getIntervalDays(ea.getLastMensesDate(), DateUtils.getCurrDate());
            } else {
                pregnantDays = DateUtils.getIntervalDays(ea.getPregnancyDate(), DateUtils.getCurrDate());
            }
            int weeks = pregnantDays / 7;
            int days = pregnantDays % 7;
            String gestationalWeeks = weeks + "周";
            if (days > 0) {
                gestationalWeeks = gestationalWeeks + days + "天";
            }
            map.put("GESTATIONAL_WEEKS", gestationalWeeks);
        } else {
            map.put("GESTATIONAL_WEEKS", "");
        }
        Set<String> flages = new HashSet<>();
        if (StringUtils.isNotBlank(ea.getFlags())) {
            List<String> flags = CommonUtil.split2List(ea.getFlags());
            for (String flag : flags) {
                flages.addAll(CommonUtil.ApplyFlag2String(ea.getFlags()));
            }
            map.put("EXAM_TYPE", StringUtils.join(flages, ","));
        }
    }


    /**
     * 获取最早时间
     *
     * @param apmCode
     * @return
     */
    public DictScheduleApmDto getTimeEarliest(String apmCode) {
        DictScheduleApmDto scheduleApm = new DictScheduleApmDto();
        if (StringUtils.isNotBlank(apmCode)) {
            QueryWrapper<DictScheduleApm> query = new QueryWrapper<>();
            query.select("SCHEDULE_APM", "TIME_EARLIEST", "TIME_SIGNIN", "TIME_START", "TIME_END", "MAX_LIMIT", "APM_LENGTH");
            query.eq("APM_CODE", apmCode);
            List<DictScheduleApm> list = dictScheduleApmMapper.selectList(query);
            if (!CollectionUtils.isEmpty(list) && list.get(0) != null) {
                String timeEarliest = StringUtils.isBlank(list.get(0).getTimeEarliest()) ? list.get(0).getTimeStart().substring(0, list.get(0).getTimeStart().length() - 3) : list.get(0).getTimeEarliest().substring(0, list.get(0).getTimeEarliest().length() - 3);
                String timeSignin = StringUtils.isBlank(list.get(0).getTimeSignin()) ? "" : list.get(0).getTimeSignin().substring(0, list.get(0).getTimeSignin().length() - 3);
                BeanUtils.copyProperties(list.get(0), scheduleApm);
                scheduleApm.setTimeEarliest(timeEarliest);
                scheduleApm.setTimeSignin(timeSignin);
                String newTimeEarliest = StringUtils.isBlank(list.get(0).getTimeEarliest()) ? "" : list.get(0).getTimeEarliest();
                String newTimeSignin = StringUtils.isBlank(list.get(0).getTimeSignin()) ? "" : list.get(0).getTimeSignin();
                scheduleApm.setNewTimeEarliest(newTimeEarliest);
                scheduleApm.setNewTimeSignin(newTimeSignin);
                scheduleApm.setScheduleApm(list.get(0).getScheduleApm());
                scheduleApm.setMaxLimit(list.get(0).getMaxLimit());
                scheduleApm.setApmLength(list.get(0).getApmLength());
            }
        }
        return scheduleApm;
    }


    public List<ExamApplyItemDto> getExamApplyItem(String mergeNo, ExamApplyDto ea) {
        ExamApplyItemDto examApplyItemDto = new ExamApplyItemDto();
        boolean isRe = false;
        if (StringUtils.isNotBlank(mergeNo)) {
            String[] mergeNos = mergeNo.split(",");
            List<String> applyNos = new ArrayList<String>();
            for (String str : mergeNos) {
                int idx = str.lastIndexOf("-");
                String applyno = str.substring(0, idx);
                if (applyNos.size() == 0 && applyno.startsWith("RE")) {
                    isRe = true;
                }
                applyNos.add(applyno);
            }
            examApplyItemDto.setApplyNos(applyNos);
        } else {
            if (ea.getApplyNo().startsWith("RE")) {
                isRe = true;
            }
            examApplyItemDto.setApplyNo(ea.getApplyNo());
        }
        List<ExamApplyItemDto> newItems;
        if (isRe) {
            newItems = examApplyItemMapper.getReItemList(examApplyItemDto);
        } else {
            newItems = examApplyItemMapper.getList(examApplyItemDto);
        }
        if (!CollectionUtils.isEmpty(newItems)) {
            List<String> list = CommonUtil.split2List(mergeNo);
            Iterator<ExamApplyItemDto> it = newItems.iterator();
            while (it.hasNext()) {
                ExamApplyItemDto item = it.next();
                String mergeNos2 = item.getApplyNo() + "-" + item.getItemNo();
                if ((!CollectionUtils.isEmpty(list)) && !list.contains(mergeNos2)) {
                    it.remove();
                }
            }
        }
        handItemCode(newItems, ea.getExamSubClass());
        return newItems;
    }

    /**
     * 去掉检查子项为空的项目
     *
     * @param items
     * @param examSubClass
     */
    public void handItemCode(List<ExamApplyItemDto> items, String examSubClass) {
        List<String> list = new ArrayList<>();
        for (ExamApplyItemDto item : items) {
            if (StringUtils.isNotBlank(examSubClass)
                    && StringUtils.isNotBlank(item.getExamSubClass())
                    && item.getExamSubClass().equals(examSubClass)) {
                list.add(item.getApplyNo() + item.getItemNo() + item.getItemCode());
            }
        }
        Iterator<ExamApplyItemDto> it = items.iterator();
        while (it.hasNext()) {
            ExamApplyItemDto e = it.next();
            String itemCode = e.getApplyNo() + e.getItemNo() + e.getItemCode();
            if (list.contains(itemCode)) {
                if (StringUtils.isNotBlank(examSubClass)
                        && StringUtils.isNotBlank(e.getExamSubClass())
                        && e.getExamSubClass().equals(examSubClass)) {
                    continue;
                }
                it.remove();
            }
            list.add(itemCode);
        }
    }

    public List<String> getOrganExamClassList() {
        String organExamClass = getConfigByName(ConstantsUtil.ConfigName.ORGAN_EXAM_CLASS.getKey());
        List<String> list = new ArrayList<>();
        if (StringUtils.isNotBlank(organExamClass)) {
            list = (List<String>) CommonUtil.split2List(organExamClass);
        }
        return list;
    }


    public List<String> getReminders(String type, String examClass, String terminalType) {
        String reserve1 = "DEFAULT";
        if (ConstantsUtil.TerminalType.DEPT.getType().equals(terminalType)) {
            reserve1 = "CLINIC";
        } else if (ConstantsUtil.TerminalType.CLINIC_IN.getType().equals(terminalType)) {
            reserve1 = "CLINIC";
        } else if (ConstantsUtil.TerminalType.CLINIC_OUT.getType().equals(terminalType)) {
            reserve1 = "CLINIC";
        } else if (ConstantsUtil.TerminalType.SELF.getType().equals(terminalType)) {
            reserve1 = "SELF";
        } else if (ConstantsUtil.TerminalType.MOBILE.getType().equals(terminalType)) {
            reserve1 = "MOBILE";
        } else if (ConstantsUtil.TerminalType.SCHEDULE_CENTER.getType().equals(terminalType)) {
            reserve1 = "CLINIC";
        } else if (ConstantsUtil.TerminalType.SCHEDULE_MANAGE.getType().equals(terminalType)) {
            reserve1 = "CLINIC";
        }
        List<String> reminders = new ArrayList<String>();
        List<DictCommonUse> list = findReminderList(type, examClass, reserve1);
        if (CollectionUtils.isEmpty(list)) {
            reserve1 = "DEFAULT";
            list = findReminderList(type, examClass, reserve1);
        }
        if (!CollectionUtils.isEmpty(list)) {
            for (int i = 0; i < list.size(); ++i) {
                reminders.add(i + 1 + "." + list.get(i).getValue());
            }
        }
        return reminders;
    }


    public List<DictCommonUse> findReminderList(String type, String examClass, String reserve1) {
        QueryWrapper<DictCommonUse> qw = new QueryWrapper<>();
        if (StringUtils.isNotBlank(type)) {
            qw.eq("NAME", type);
        } else {
            qw.in("NAME", "REMINDER_SIGN", "REMINDER_SCHEDULE");
        }
        if (StringUtils.isNotBlank(examClass)) {
            qw.in("EXAM_CLASS", CommonUtil.split2List(examClass));
        }

        if (StringUtils.isNotBlank(reserve1)) {
            qw.in("RESERVE1", CommonUtil.split2List(reserve1));
        }
        qw.orderByAsc("NAME", "SORT_NO");
        List<DictCommonUse> list = dictCommonUseMapper.selectList(qw);
        return list;
    }


    public List<ExamSchedule> getExamScheduleByNxtApm(ExamScheduleDto dto) {
        QueryWrapper<ExamSchedule> qw = new QueryWrapper<>();
        qw.like("NEXT_APM_RATIO", dto.getApmCode());
        qw.eq("SCHEDULED_DATE", dto.getScheduledDate());
        return examScheduleMapper.selectList(qw);
    }


    public void addExamScheduleAct(ExamApplyDto ea) {
        ExamScheduleAct act = new ExamScheduleAct();
        act.setApplyNo(ea.getApplyNo());
        act.setActType(ea.getActType());
        act.setScheduleDate(ea.getScheduleDate());
        act.setScheduleApm(ea.getScheduleApm());
        act.setQueueName(ea.getQueueName());
        act.setHospitalCode(ea.getHospitalCode());
        String userType = ConstantsUtil.UserType.DOCTOR.getType();
        act.setUserType(userType);
//        act.setUserId(dictUsers.getUserId());
//        act.setUserName(dictUsers.getName());
//        act.setComputerName(dictUsers.getIpAddress());
        act.setTerminalType(ea.getTerminalType());
        String dateStr = ConstantsUtil.YMDHMS.format(new Date());
        String[] dateArr = dateStr.split(" ");
        act.setActDate(dateArr[0]);
        act.setActTime(dateArr[1]);
        act.setScheduledId(ea.getScheduledId());
        String actDescription = ea.getActDescription();
        if (StringUtils.isBlank(actDescription)) {
            StringBuilder bf = new StringBuilder();
            if (StringUtils.isNotBlank(ea.getName())) {
                bf.append(ea.getName()).append(",");
            }
            if (StringUtils.isNotBlank(ea.getSex())) {
                bf.append(ea.getSex()).append(",");
            }
            if (StringUtils.isNotBlank(ea.getAge())) {
                bf.append(ea.getAge()).append(",");
            }
            if (StringUtils.isNotBlank(ea.getSickId())) {
                bf.append("ID:").append(ea.getSickId()).append(",");
            }
            if (StringUtils.isNotBlank(ea.getScheduledId())) {
                bf.append("预约ID:").append(ea.getScheduledId()).append(",");
            }
            if (StringUtils.isNotBlank(ea.getExamClass())) {
                bf.append("检查类别:").append(ea.getExamClass()).append(",");
            }
            if (ea.getItems() != null && ea.getItems().size() > 0) {
                for (ExamApplyItemDto item : ea.getItems()) {
                    bf.append(",申请单号:" + item.getApplyNo() + ",项目序号:" + item.getItemNo() + ",项目名称:" + item.getItemName());
                }
            }
            if ("2".equals(ea.getActType()) && StringUtils.isNotBlank(ea.getCancelMemo())) {
                bf.append(",取消备注:" + ea.getCancelMemo());
            }
            if (StringUtils.isNotBlank(ea.getDesc())) {
                bf.append(ea.getDesc());
            }
            if (StringUtils.isNotBlank(ea.getProcess())) {
                String process = " 系数:" + ea.getProcess();
                if (StringUtils.isNotBlank(ea.getNextOrganProcess())) {
                    process = process + " ,跨系:" + ea.getNextOrganProcess().substring(1);
                }
                bf.append(process);
            }
            actDescription = bf.toString();
        }
        act.setActDescription(actDescription);

        long maxActNo = examScheduleActMapper.getMaxActNo();
        act.setActNo(String.valueOf(maxActNo + 1L));
        examScheduleActMapper.insert(act);
    }


    /**
     * 修改保存预约ID
     *
     * @param entity
     * @return
     */
    public int editExamScheduleById(ExamSchedule entity) {
        UpdateWrapper<ExamSchedule> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("SCHEDULED_ID", entity.getScheduledId());
        return examScheduleMapper.update(entity, updateWrapper);
    }

    /**
     * 获取已预约未报道的申请单信息
     */
    public List<ScheduledExamApplyInfoDto> queryScheduleApplies(QueryScheduledAppliesDto dto) {
        List<ScheduledExamApplyInfoDto> scheduledExamApplyInfoDtos = examScheduleMapper.queryScheduleApplies(dto);
        return scheduledExamApplyInfoDtos;
    }


    /**
     * 获取未报到的申请单列表
     *
     * @return
     */
    public List<ExamApplyItemBaseInfoDto> getNoScheduledApplies(List<String> classs) {
        Date date = DateUtils.addMinutes(new Date(), -15);
        String dateStr = DateUtils.format(date, DateUtils.PATTERN_DATE);
        String timeStr = DateUtils.format(date, DateUtils.PATTERN_TIME);
        List<ExamApplyItemBaseInfoDto> applyNoList = examScheduleMapper.getNoScheduledApplies(classs, dateStr, timeStr);
        return applyNoList;
    }


}
